// ****************************************************************************
// *     Filename:  DetectorConstruction.cc
// *      Created:  2012-09-14 11:34:20
// *      Version:  1.0
// *     Revision:  0
// *       Author:  Tran Hoai Nam (nam), nam@kuno-g.phys.sci.osaka-u.ac.jp
// * Organization:  Osaka University
// *      License:  Geant4 Software License 
// *                http://geant4.cern.ch/license/LICENSE.html
// *  Description:  
// ****************************************************************************
#include "DetectorConstruction.hh"
#include "MySD.hh"
//Material and geometry
#include "G4Material.hh"
#include "G4NistManager.hh"     
#include "G4Box.hh"
#include "G4Tubs.hh"
#include "G4LogicalVolume.hh"
#include "G4ThreeVector.hh"
#include "G4PVPlacement.hh"
#include "G4Sphere.hh"
#include "G4SDManager.hh"
#include "G4Colour.hh"
#include "G4VisAttributes.hh"
#include "G4RotationMatrix.hh"
#include "G4SubtractionSolid.hh"
#include "G4UnionSolid.hh"
#include "G4IntersectionSolid.hh"

#include "G4RunManager.hh"
//Field 
#include "G4FieldManager.hh"
#include "G4TransportationManager.hh"
#include "G4UniformMagField.hh"
#include "G4ChordFinder.hh"
#include "G4Mag_UsualEqRhs.hh"
#include "G4ClassicalRK4.hh"

#include "globals.hh"

DetectorConstruction::DetectorConstruction() : fpPhysWorld(0)
{
	DefineMaterials();
	SetColors();
	SetDefaultParameters();
	SetMagField(3*tesla,0,0);
	CalculateSize();
}

DetectorConstruction::~DetectorConstruction()
{; }

void DetectorConstruction::CalculateSize()
{
}
void DetectorConstruction::SetMagField(G4double Bx, G4double By, G4double Bz)
{
	G4UniformMagField* myField =
		new G4UniformMagField(G4ThreeVector(Bx,By,Bz));//Bx
	G4Mag_UsualEqRhs* myEquation = new G4Mag_UsualEqRhs(myField);
	G4MagIntegratorStepper* myStepper = new G4ClassicalRK4(myEquation);
	G4ChordFinder* myChordFinder = new G4ChordFinder(myField,0.01*mm,myStepper);
	fpFieldMan = new G4FieldManager(myField,myChordFinder);
}
void DetectorConstruction::SetDefaultParameters()
{
	fWorldX = 50*cm;
	fWorldY = 50*cm;
	fWorldZ = 50*cm;
}

G4VPhysicalVolume* DetectorConstruction::Construct()
{
	// World volume, beam in +z direction
	G4Box* BoxWorld
		= new G4Box("Worldbox",fWorldX/2,fWorldY/2,fWorldZ/2);
	G4LogicalVolume *logWorld;
	logWorld = new G4LogicalVolume(BoxWorld, fVacuum,"Worldlog",0,0,0); 
	fpPhysWorld = new G4PVPlacement(0,G4ThreeVector(),
			logWorld,"expHall",0,false,0);
	logWorld->SetVisAttributes(G4VisAttributes::Invisible); //Set invisible
	
	// A detector
	G4double fDet1X = 10*cm;
	G4double fDet1Y = 10*cm;
	G4double fDet1Z = 0.5*mm;

	G4Box* BoxDet1 = new G4Box("Det1Box", fDet1X/2, fDet1Y/2, fDet1Z/2);
	G4LogicalVolume* logDet1 = new G4LogicalVolume(BoxDet1, fPScinti, "logDet1");
	new G4PVPlacement(0, G4ThreeVector(0.,0.,- fWorldZ/4), 
			logDet1,"physDet1",logWorld,false,0);
  logDet1->SetVisAttributes(fpGreen);

	G4double fWin1X = 10*cm;
	G4double fWin1Y = 10*cm;
	G4double fWin1Z = 0.2*mm;
	G4Box* BoxWin1 = new G4Box("Win1Box", fWin1X/2, fWin1Y/2, fWin1Z/2);
	G4LogicalVolume* logWin1 = new G4LogicalVolume(BoxWin1, fpMylar, "logWin1");
	new G4PVPlacement(0, G4ThreeVector(0.,0.,- fWorldZ/4+6*mm), 
			logWin1,"physWin1",logWorld,false,0);
  logWin1->SetVisAttributes(fpGrey);

	G4double fDet2X = 15*cm;
	G4double fDet2Y = 15*cm;
	G4double fDet2Z = 0.2*mm;
	G4RotationMatrix *rm3 = new G4RotationMatrix(); 
	rm3->rotateY(-45*deg);

	G4Box* BoxDet2 = new G4Box("Det2Box", fDet2X/2, fDet2Y/2, fDet2Z/2);
	G4LogicalVolume* logDet2 = new G4LogicalVolume(BoxDet2, fAluminum, "logDet2");
	new G4PVPlacement(rm3, G4ThreeVector(0.,0.,- fWorldZ/4 + 21*cm), 
			logDet2,"physDet2",logWorld,false,0);
  logDet2->SetVisAttributes(fpRed);
	//Sensitive detector definition
	G4SDManager* SDman = G4SDManager::GetSDMpointer();
	G4VSensitiveDetector* aSD1 = new MySD("aSD1"); 
	SDman->AddNewDetector(aSD1);
	logDet1->SetSensitiveDetector(aSD1);
	G4VSensitiveDetector* aSD2 = new MySD("aSD2"); 
	SDman->AddNewDetector(aSD2);
	logDet2->SetSensitiveDetector(aSD2);

	// Dummy box, for magnetic field setting
	//G4Box* BoxDummy = new G4Box("DummyBox",fDet1X/2, fDet1Y/2, fDet1Z*5);
	//G4LogicalVolume* logDummy = new G4LogicalVolume(BoxDummy,fVacuum,"logDummy");
	//logDummy->SetFieldManager(fpFieldMan,false); 
	//true: force field to all daughters
	//new G4PVPlacement(0,G4ThreeVector(0.,0.,0.),
			//logDummy,"physDummy",logWorld,false,0);
  //G4VisAttributes* yellow = new G4VisAttributes(G4Colour::Yellow());
  //logDummy->SetVisAttributes(yellow);

	return fpPhysWorld;
}

void DetectorConstruction::DefineMaterials()
{
	G4NistManager* man = G4NistManager::Instance();
	fVacuum = man->FindOrBuildMaterial("G4_Galactic");
	fAir = man->FindOrBuildMaterial("G4_AIR");
	fCopper = man->FindOrBuildMaterial("G4_Cu");
	fAluminum = man->FindOrBuildMaterial("G4_Al");
	fNaI = man->FindOrBuildMaterial("G4_SODIUM_IODIDE");
	fSilicon = man->FindOrBuildMaterial("G4_Si");
	fLead = man->FindOrBuildMaterial("G4_Pb");
	fPScinti = man->FindOrBuildMaterial("G4_PLASTIC_SC_VINYLTOLUENE");

	G4double density;
	G4int ncomponents;
	G4double fractionmass;
	fSSteel = new G4Material("StainlessSteel", density= 8.06*g/cm3, ncomponents=6);
	G4Element *C = man->FindOrBuildElement("C");
	G4Element *Si = man->FindOrBuildElement("Si");
	G4Element *Cr = man->FindOrBuildElement("Cr");
	G4Element *Mn = man->FindOrBuildElement("Mn");
	G4Element *Fe = man->FindOrBuildElement("Fe");
	G4Element *Ni = man->FindOrBuildElement("Ni");
	fSSteel->AddElement(C, fractionmass=0.001);
	fSSteel->AddElement(Si, fractionmass=0.007);
	fSSteel->AddElement(Cr, fractionmass=0.18);
	fSSteel->AddElement(Mn, fractionmass=0.01);
	fSSteel->AddElement(Fe, fractionmass=0.712);
	fSSteel->AddElement(Ni, fractionmass=0.09);
	fpMylar = man->FindOrBuildMaterial("G4_MYLAR");
}

void DetectorConstruction::SetColors() 
{
	fpYellow = new G4VisAttributes(G4Colour::Yellow());
	fpGreen = new G4VisAttributes(G4Colour::Green());
	//fpBlue = new G4VisAttributes(G4Colour::Blue());
	fpBlue = new G4VisAttributes(G4Colour(0.1,.7,1.));
	fpRed = new G4VisAttributes(G4Colour::Red());
	fpCyan = new G4VisAttributes(G4Colour::Cyan());
	fpMagenta = new G4VisAttributes(G4Colour::Magenta());
	fpGrey = new G4VisAttributes(G4Colour::Grey());
	fpTransGrey = new G4VisAttributes(G4Colour(0.5,0.5,0.5,0.1));
	fpTransYellow = new G4VisAttributes(G4Colour(1, 1.0, 0.0, 0.01));
}
